library(tidyverse)
library(Seurat)
library(patchwork)
library(SingleR)
library(celldex)
library(pheatmap)

# Speeds up scTransform
#BiocManager::install("glmGamPoi")
# Load AR and Tol datasets
AR_data <- CreateSeuratObject(Read10X(data.dir = "~/Desktop/R_projects/Dr_Krummey_Lab/heartTransplant_data/GSE262851_RAW/AR/"), min.cells = 3, min.features = 200)
AR_data$condition <-  "AR"
AR_data <- PercentageFeatureSet(AR_data, pattern = "^mt-", col.name = "percent.mt")

VlnPlot(AR_data, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"))
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# I filtered a bit looser, nFeatureRNA > 5000 vs 2500, percent.mt < 15 vs 5
AR_data <- subset(AR_data, subset = nFeature_RNA > 200 & nFeature_RNA < 5000 & percent.mt < 15)
VlnPlot(AR_data, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"))
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

Tol_data <- CreateSeuratObject(Read10X(data.dir = "~/Desktop/R_projects/Dr_Krummey_Lab/heartTransplant_data/GSE262851_RAW/Tol/"), min.cells = 3, min.features = 200)
Tol_data$condition <- "Tol"
Tol_data <- PercentageFeatureSet(Tol_data, pattern = "^mt-", col.name = "percent.mt")
VlnPlot(Tol_data, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"))
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

Tol_data <- subset(Tol_data, subset = nFeature_RNA > 200 & nFeature_RNA < 5000 & percent.mt < 15)
VlnPlot(Tol_data, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"))
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# Lets merge asap so we know the same transformations are applied
# Project is just a label to group the merged datasets and I never reference it. Feel free to change!
data.merge <- merge(AR_data, Tol_data, add.cell.ids = c("AR", "Tol"), project = "Heart")
# SCTransform instead of normalize -> variable features -> scale. More up-to-date
data.merge <- SCTransform(data.merge, vars.to.regress = "percent.mt", verbose = FALSE)
data.merge <- RunPCA(data.merge, verbose = FALSE)

# dims of PCA to choose. Probably some fine tuning here for dims and number of neighbors, but I think it looks fine enough already
# It is always good to be thinking whether you are overfitting or underfitting data though!
data.merge = FindNeighbors(data.merge, dims = 1:30, reduction = "pca")
Computing nearest neighbor graph
Computing SNN
data.merge = FindClusters(data.merge, resolution = 0.5, cluster.name = "unintegrated_clusters")
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 5321
Number of edges: 181553

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8922
Number of communities: 17
Elapsed time: 0 seconds
data.merge <- RunUMAP(data.merge, dims = 1:30, reduction = "pca", reduction.name = "umap.unintegrated", verbose = FALSE)

# Always visualize!
# The plot is showing batch effects, so we definitely need to integrate
DimPlot(data.merge, reduction = "umap.unintegrated", group.by = c("condition", "unintegrated_clusters"), combine = FALSE)
[[1]]

[[2]]

# Now we integrate the two layers using the Harmony algorithm with the PCA we calculated 
data.integrated <- IntegrateLayers(object = data.merge, method = HarmonyIntegration, orig.reduction = "pca", new.reduction = "harmony", normalization.method = "SCT", verbose = FALSE)
Warning: HarmonyMatrix is deprecated and will be removed in the future from the API in the future
# After integrating we re-find our neighbors and clusters and run UMAP to check our batch effects visually
data.integrated <- FindNeighbors(data.integrated, reduction = "harmony", dims = 1:30)
Computing nearest neighbor graph
Computing SNN
data.integrated <- FindClusters(data.integrated, resolution = 0.5, cluster.name = "harmony_clusters")
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 5321
Number of edges: 188646

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8902
Number of communities: 14
Elapsed time: 0 seconds
data.integrated <- RunUMAP(data.integrated, reduction = "harmony", dims = 1:30, reduction.name = "umap.harmony", verbose = FALSE)

# Much nicer, AR and TOL form well-mixed clusters
DimPlot(data.integrated, reduction = "umap.harmony", group.by = c("condition", "harmony_clusters"), combine = FALSE)
[[1]]

[[2]]

# I would suggest looking into Azimuth instead of SingleR. Better fine labeling
ref <- celldex::ImmGenData()
data.integrated_fine_pred <- SingleR(test = GetAssayData(data.integrated, layer = 'counts'), 
                   ref = ref, 
                   labels = ref$label.fine)

data.integrated_main_pred <- SingleR(test = GetAssayData(data.integrated, layer = 'counts'), 
                   ref = ref, 
                   labels = ref$label.main)
data.integrated$singleR.labels.fine <- data.integrated_fine_pred$labels[match(rownames(data.integrated@meta.data), rownames(data.integrated_fine_pred))]

data.integrated$singleR.labels.main <- data.integrated_main_pred$labels[match(rownames(data.integrated@meta.data), rownames(data.integrated_main_pred))]
DimPlot(data.integrated, reduction = "umap.harmony", group.by = "singleR.labels.main")

DimPlot(data.integrated, reduction = "umap.harmony", group.by = "singleR.labels.fine")

head(sort(table(data.integrated_fine_pred$labels), decreasing=TRUE))

Macrophages (MF.11CLOSER.SALM3)           Monocytes (MO.6C+II-) 
                           1408                             561 
    T cells (T.8EFF.OT1.D10LIS)    Macrophages (MF.103-11B+24-) 
                            298                             228 
        Endothelial cells (BEC)       Macrophages (MF.II+480LO) 
                            219                             204 
head(sort(table(data.integrated_main_pred$labels), decreasing=TRUE))

      Macrophages           T cells         Monocytes               NKT 
             2807               826               352               334 
          B cells Endothelial cells 
              271               220 
# 826 T cells
# Finding more ways to plot our results, checking annotation of cells and pruned cells
plotScoreHeatmap(data.integrated_main_pred)

plotDeltaDistribution(data.integrated_main_pred)

Change the filtering to include all T Cells EXCEPT CD4 T Cells!

View(data_frame(data.integrated@meta.data[["singleR.labels.fine"]]))
View(table(data.integrated@meta.data$singleR.labels.fine))
# Exclude CD4 T cells (using negative lookahead regex)
pattern <- "T cells \\((?!CD4).*\\)"

# Shorter way to add metadata
# Need to add perl = TRUE for the regex to be compatible
data.integrated$non_cd4 <- grepl(pattern, data.integrated@meta.data$singleR.labels.fine, perl = TRUE)

DimPlot(data.integrated, reduction = "umap.harmony", group.by = "non_cd4")


non_cd4_subset <- subset(data.integrated, subset = non_cd4 == TRUE)
# Rerun SCTransform on the subset, since the global structure of variance changed 
non_cd4_subset <- SCTransform(non_cd4_subset, vars.to.regress = "percent.mt", verbose = FALSE)
Warning: Different cells and/or features from existing assay SCT
# Sub-clustering of non_cd4 cells
non_cd4_subset <- RunPCA(non_cd4_subset, reduction.name = "non_cd4.pca", verbose = FALSE)
Warning: Key ‘PC_’ taken, using ‘noncd4pca_’ instead
non_cd4_subset <- FindNeighbors(non_cd4_subset, reduction = "non_cd4.pca", dims = 1:30)
Computing nearest neighbor graph
Computing SNN
non_cd4_subset <- FindClusters(non_cd4_subset, resolution = 0.5, cluster.name = "non_cd4_clusters")
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 1176
Number of edges: 47342

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.6982
Number of communities: 6
Elapsed time: 0 seconds
non_cd4_subset <- RunUMAP(non_cd4_subset, dims = 1:30, reduction = "non_cd4.pca", verbose = FALSE, reduction.name = "non_cd4.umap")
DimPlot(non_cd4_subset, reduction = "non_cd4.umap", group.by = c("condition", "non_cd4_clusters"), combine = FALSE)
[[1]]

[[2]]

# Finding DE genes
Idents(non_cd4_subset) <- "non_cd4_clusters"
non_cd4_subset <- PrepSCTFindMarkers(non_cd4_subset)
Found 2 SCT models. Recorrecting SCT counts using minimum median counts: 5504

  |                                                  | 0 % ~calculating  
  |+++++++++++++++++++++++++                         | 50% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  
tcell.non_cd4.markers <- FindMarkers(non_cd4_subset, ident.1 = 0, ident.2 = 2)

  |                                                  | 0 % ~calculating  
  |+                                                 | 1 % ~16s          
  |+                                                 | 2 % ~16s          
  |++                                                | 3 % ~16s          
  |++                                                | 4 % ~16s          
  |+++                                               | 5 % ~16s          
  |+++                                               | 6 % ~16s          
  |++++                                              | 7 % ~15s          
  |++++                                              | 8 % ~16s          
  |+++++                                             | 9 % ~15s          
  |+++++                                             | 10% ~15s          
  |++++++                                            | 11% ~15s          
  |++++++                                            | 12% ~15s          
  |+++++++                                           | 13% ~15s          
  |+++++++                                           | 14% ~15s          
  |++++++++                                          | 15% ~14s          
  |++++++++                                          | 16% ~14s          
  |+++++++++                                         | 17% ~14s          
  |+++++++++                                         | 18% ~14s          
  |++++++++++                                        | 19% ~14s          
  |++++++++++                                        | 20% ~14s          
  |+++++++++++                                       | 21% ~13s          
  |+++++++++++                                       | 22% ~13s          
  |++++++++++++                                      | 23% ~13s          
  |++++++++++++                                      | 24% ~13s          
  |+++++++++++++                                     | 25% ~13s          
  |+++++++++++++                                     | 26% ~13s          
  |++++++++++++++                                    | 27% ~13s          
  |++++++++++++++                                    | 28% ~12s          
  |+++++++++++++++                                   | 29% ~12s          
  |+++++++++++++++                                   | 30% ~12s          
  |++++++++++++++++                                  | 31% ~12s          
  |++++++++++++++++                                  | 32% ~12s          
  |+++++++++++++++++                                 | 33% ~11s          
  |+++++++++++++++++                                 | 34% ~11s          
  |++++++++++++++++++                                | 35% ~11s          
  |++++++++++++++++++                                | 36% ~11s          
  |+++++++++++++++++++                               | 37% ~11s          
  |+++++++++++++++++++                               | 38% ~11s          
  |++++++++++++++++++++                              | 39% ~10s          
  |++++++++++++++++++++                              | 40% ~10s          
  |+++++++++++++++++++++                             | 41% ~10s          
  |+++++++++++++++++++++                             | 42% ~10s          
  |++++++++++++++++++++++                            | 43% ~10s          
  |++++++++++++++++++++++                            | 44% ~09s          
  |+++++++++++++++++++++++                           | 45% ~09s          
  |+++++++++++++++++++++++                           | 46% ~09s          
  |++++++++++++++++++++++++                          | 47% ~09s          
  |++++++++++++++++++++++++                          | 48% ~09s          
  |+++++++++++++++++++++++++                         | 49% ~09s          
  |+++++++++++++++++++++++++                         | 50% ~08s          
  |++++++++++++++++++++++++++                        | 51% ~08s          
  |++++++++++++++++++++++++++                        | 52% ~08s          
  |+++++++++++++++++++++++++++                       | 53% ~08s          
  |+++++++++++++++++++++++++++                       | 54% ~08s          
  |++++++++++++++++++++++++++++                      | 55% ~08s          
  |++++++++++++++++++++++++++++                      | 56% ~07s          
  |+++++++++++++++++++++++++++++                     | 57% ~07s          
  |+++++++++++++++++++++++++++++                     | 58% ~07s          
  |++++++++++++++++++++++++++++++                    | 59% ~07s          
  |++++++++++++++++++++++++++++++                    | 60% ~07s          
  |+++++++++++++++++++++++++++++++                   | 61% ~07s          
  |+++++++++++++++++++++++++++++++                   | 62% ~06s          
  |++++++++++++++++++++++++++++++++                  | 63% ~06s          
  |++++++++++++++++++++++++++++++++                  | 64% ~06s          
  |+++++++++++++++++++++++++++++++++                 | 65% ~06s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~06s          
  |++++++++++++++++++++++++++++++++++                | 67% ~06s          
  |++++++++++++++++++++++++++++++++++                | 68% ~05s          
  |+++++++++++++++++++++++++++++++++++               | 69% ~05s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~05s          
  |++++++++++++++++++++++++++++++++++++              | 71% ~05s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~05s          
  |+++++++++++++++++++++++++++++++++++++             | 73% ~05s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~04s          
  |++++++++++++++++++++++++++++++++++++++            | 75% ~04s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~04s          
  |+++++++++++++++++++++++++++++++++++++++           | 77% ~04s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~04s          
  |++++++++++++++++++++++++++++++++++++++++          | 79% ~04s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~03s          
  |+++++++++++++++++++++++++++++++++++++++++         | 81% ~03s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~03s          
  |++++++++++++++++++++++++++++++++++++++++++        | 83% ~03s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~03s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~03s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~02s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~02s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~02s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~01s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=17s  
tcell.non_cd4.markers
FeaturePlot(non_cd4_subset, features = "Gcnt1", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Gzmb", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Spn", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Sell", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Prf1", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Spn", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Cxcr3", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Havcr2", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Ifng", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Icos", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Prdm1", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Tox", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Gzmk", reduction = "non_cd4.umap")

#FeaturePlot(non_cd4_subset, features = "Gbma", reduction = "non_cd4.umap") NOT FOUND
#FeaturePlot(non_cd4_subset, features = "Gzmh", reduction = "non_cd4.umap") NOT FOUND
FeaturePlot(non_cd4_subset, features = "Gzmb", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Lag3", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Tigit", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Irf4", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Tcf7", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Pdcd1", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Tnf", reduction = "non_cd4.umap")

FeaturePlot(non_cd4_subset, features = "Tbx21", reduction = "non_cd4.umap")

#Save the plots as PNGs

library(ggplot2)

List genes (remove genes that were not found)

genes <- c(“Gcnt1”, “Gzmb”, “Spn”, “Sell”, “Prf1”, “Cxcr3”, “Havcr2”, “Ifng”, “Icos”, “Prdm1”, “Tox”, “Gzmk”, “Lag3”, “Tigit”, “Irf4”, “Tcf7”, “Pdcd1”, “Tnf”, “Tbx21”)

Loop through the genes and create/save plots

for (gene in genes) { plot <- FeaturePlot(non_cd4_subset, features = gene, reduction = “non_cd4.umap”) ggsave(filename = paste0(“non_cd4_”, gene, “.png”), plot = plot, width = 6, height = 4, dpi = 300)

# From the list Dr. Krummey sent, find the differential expression of the genes of interest
# Look back to just NON-CD4 T cells to see if there is a difference (complete)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBkZl9wcmludDogcGFnZWQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3IgTG9hZCBQYWNrYWdlc30KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShTaW5nbGVSKQpsaWJyYXJ5KGNlbGxkZXgpCmxpYnJhcnkocGhlYXRtYXApCgojIFNwZWVkcyB1cCBzY1RyYW5zZm9ybQojQmlvY01hbmFnZXI6Omluc3RhbGwoImdsbUdhbVBvaSIpCmBgYAoKYGBge3J9CiMgTG9hZCBBUiBhbmQgVG9sIGRhdGFzZXRzCkFSX2RhdGEgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KFJlYWQxMFgoZGF0YS5kaXIgPSAifi9EZXNrdG9wL1JfcHJvamVjdHMvRHJfS3J1bW1leV9MYWIvaGVhcnRUcmFuc3BsYW50X2RhdGEvR1NFMjYyODUxX1JBVy9BUi8iKSwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpBUl9kYXRhJGNvbmRpdGlvbiA8LSAgIkFSIgpBUl9kYXRhIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KEFSX2RhdGEsIHBhdHRlcm4gPSAiXm10LSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKQoKVmxuUGxvdChBUl9kYXRhLCBmZWF0dXJlcyA9IGMoIm5Db3VudF9STkEiLCAibkZlYXR1cmVfUk5BIiwgInBlcmNlbnQubXQiKSkKIyBJIGZpbHRlcmVkIGEgYml0IGxvb3NlciwgbkZlYXR1cmVSTkEgPiA1MDAwIHZzIDI1MDAsIHBlcmNlbnQubXQgPCAxNSB2cyA1CkFSX2RhdGEgPC0gc3Vic2V0KEFSX2RhdGEsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDIwMCAmIG5GZWF0dXJlX1JOQSA8IDUwMDAgJiBwZXJjZW50Lm10IDwgMTUpClZsblBsb3QoQVJfZGF0YSwgZmVhdHVyZXMgPSBjKCJuQ291bnRfUk5BIiwgIm5GZWF0dXJlX1JOQSIsICJwZXJjZW50Lm10IikpCgpUb2xfZGF0YSA8LSBDcmVhdGVTZXVyYXRPYmplY3QoUmVhZDEwWChkYXRhLmRpciA9ICJ+L0Rlc2t0b3AvUl9wcm9qZWN0cy9Ecl9LcnVtbWV5X0xhYi9oZWFydFRyYW5zcGxhbnRfZGF0YS9HU0UyNjI4NTFfUkFXL1RvbC8iKSwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwKQpUb2xfZGF0YSRjb25kaXRpb24gPC0gIlRvbCIKVG9sX2RhdGEgPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoVG9sX2RhdGEsIHBhdHRlcm4gPSAiXm10LSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKQpWbG5QbG90KFRvbF9kYXRhLCBmZWF0dXJlcyA9IGMoIm5Db3VudF9STkEiLCAibkZlYXR1cmVfUk5BIiwgInBlcmNlbnQubXQiKSkKVG9sX2RhdGEgPC0gc3Vic2V0KFRvbF9kYXRhLCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiAyMDAgJiBuRmVhdHVyZV9STkEgPCA1MDAwICYgcGVyY2VudC5tdCA8IDE1KQpWbG5QbG90KFRvbF9kYXRhLCBmZWF0dXJlcyA9IGMoIm5Db3VudF9STkEiLCAibkZlYXR1cmVfUk5BIiwgInBlcmNlbnQubXQiKSkKCiMgTGV0cyBtZXJnZSBhc2FwIHNvIHdlIGtub3cgdGhlIHNhbWUgdHJhbnNmb3JtYXRpb25zIGFyZSBhcHBsaWVkCiMgUHJvamVjdCBpcyBqdXN0IGEgbGFiZWwgdG8gZ3JvdXAgdGhlIG1lcmdlZCBkYXRhc2V0cyBhbmQgSSBuZXZlciByZWZlcmVuY2UgaXQuIEZlZWwgZnJlZSB0byBjaGFuZ2UhCmRhdGEubWVyZ2UgPC0gbWVyZ2UoQVJfZGF0YSwgVG9sX2RhdGEsIGFkZC5jZWxsLmlkcyA9IGMoIkFSIiwgIlRvbCIpLCBwcm9qZWN0ID0gIkhlYXJ0IikKYGBgCgpgYGB7cn0KIyBTQ1RyYW5zZm9ybSBpbnN0ZWFkIG9mIG5vcm1hbGl6ZSAtPiB2YXJpYWJsZSBmZWF0dXJlcyAtPiBzY2FsZS4gTW9yZSB1cC10by1kYXRlCmRhdGEubWVyZ2UgPC0gU0NUcmFuc2Zvcm0oZGF0YS5tZXJnZSwgdmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiLCB2ZXJib3NlID0gRkFMU0UpCmRhdGEubWVyZ2UgPC0gUnVuUENBKGRhdGEubWVyZ2UsIHZlcmJvc2UgPSBGQUxTRSkKCiMgZGltcyBvZiBQQ0EgdG8gY2hvb3NlLiBQcm9iYWJseSBzb21lIGZpbmUgdHVuaW5nIGhlcmUgZm9yIGRpbXMgYW5kIG51bWJlciBvZiBuZWlnaGJvcnMsIGJ1dCBJIHRoaW5rIGl0IGxvb2tzIGZpbmUgZW5vdWdoIGFscmVhZHkKIyBJdCBpcyBhbHdheXMgZ29vZCB0byBiZSB0aGlua2luZyB3aGV0aGVyIHlvdSBhcmUgb3ZlcmZpdHRpbmcgb3IgdW5kZXJmaXR0aW5nIGRhdGEgdGhvdWdoIQpkYXRhLm1lcmdlID0gRmluZE5laWdoYm9ycyhkYXRhLm1lcmdlLCBkaW1zID0gMTozMCwgcmVkdWN0aW9uID0gInBjYSIpCmRhdGEubWVyZ2UgPSBGaW5kQ2x1c3RlcnMoZGF0YS5tZXJnZSwgcmVzb2x1dGlvbiA9IDAuNSwgY2x1c3Rlci5uYW1lID0gInVuaW50ZWdyYXRlZF9jbHVzdGVycyIpCmRhdGEubWVyZ2UgPC0gUnVuVU1BUChkYXRhLm1lcmdlLCBkaW1zID0gMTozMCwgcmVkdWN0aW9uID0gInBjYSIsIHJlZHVjdGlvbi5uYW1lID0gInVtYXAudW5pbnRlZ3JhdGVkIiwgdmVyYm9zZSA9IEZBTFNFKQoKIyBBbHdheXMgdmlzdWFsaXplIQojIFRoZSBwbG90IGlzIHNob3dpbmcgYmF0Y2ggZWZmZWN0cywgc28gd2UgZGVmaW5pdGVseSBuZWVkIHRvIGludGVncmF0ZQpEaW1QbG90KGRhdGEubWVyZ2UsIHJlZHVjdGlvbiA9ICJ1bWFwLnVuaW50ZWdyYXRlZCIsIGdyb3VwLmJ5ID0gYygiY29uZGl0aW9uIiwgInVuaW50ZWdyYXRlZF9jbHVzdGVycyIpLCBjb21iaW5lID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgTm93IHdlIGludGVncmF0ZSB0aGUgdHdvIGxheWVycyB1c2luZyB0aGUgSGFybW9ueSBhbGdvcml0aG0gd2l0aCB0aGUgUENBIHdlIGNhbGN1bGF0ZWQgCmRhdGEuaW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVMYXllcnMob2JqZWN0ID0gZGF0YS5tZXJnZSwgbWV0aG9kID0gSGFybW9ueUludGVncmF0aW9uLCBvcmlnLnJlZHVjdGlvbiA9ICJwY2EiLCBuZXcucmVkdWN0aW9uID0gImhhcm1vbnkiLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJTQ1QiLCB2ZXJib3NlID0gRkFMU0UpCmBgYAoKYGBge3J9CiMgQWZ0ZXIgaW50ZWdyYXRpbmcgd2UgcmUtZmluZCBvdXIgbmVpZ2hib3JzIGFuZCBjbHVzdGVycyBhbmQgcnVuIFVNQVAgdG8gY2hlY2sgb3VyIGJhdGNoIGVmZmVjdHMgdmlzdWFsbHkKZGF0YS5pbnRlZ3JhdGVkIDwtIEZpbmROZWlnaGJvcnMoZGF0YS5pbnRlZ3JhdGVkLCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIGRpbXMgPSAxOjMwKQpkYXRhLmludGVncmF0ZWQgPC0gRmluZENsdXN0ZXJzKGRhdGEuaW50ZWdyYXRlZCwgcmVzb2x1dGlvbiA9IDAuNSwgY2x1c3Rlci5uYW1lID0gImhhcm1vbnlfY2x1c3RlcnMiKQpkYXRhLmludGVncmF0ZWQgPC0gUnVuVU1BUChkYXRhLmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJoYXJtb255IiwgZGltcyA9IDE6MzAsIHJlZHVjdGlvbi5uYW1lID0gInVtYXAuaGFybW9ueSIsIHZlcmJvc2UgPSBGQUxTRSkKCiMgTXVjaCBuaWNlciwgQVIgYW5kIFRPTCBmb3JtIHdlbGwtbWl4ZWQgY2x1c3RlcnMKRGltUGxvdChkYXRhLmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9IGMoImNvbmRpdGlvbiIsICJoYXJtb255X2NsdXN0ZXJzIiksIGNvbWJpbmUgPSBGQUxTRSkKYGBgCgoKYGBge3J9CiMgSSB3b3VsZCBzdWdnZXN0IGxvb2tpbmcgaW50byBBemltdXRoIGluc3RlYWQgb2YgU2luZ2xlUi4gQmV0dGVyIGZpbmUgbGFiZWxpbmcKcmVmIDwtIGNlbGxkZXg6OkltbUdlbkRhdGEoKQpgYGAKCmBgYHtyfQpkYXRhLmludGVncmF0ZWRfZmluZV9wcmVkIDwtIFNpbmdsZVIodGVzdCA9IEdldEFzc2F5RGF0YShkYXRhLmludGVncmF0ZWQsIGxheWVyID0gJ2NvdW50cycpLCAKICAgICAgICAgICAgICAgICAgIHJlZiA9IHJlZiwgCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSByZWYkbGFiZWwuZmluZSkKCmRhdGEuaW50ZWdyYXRlZF9tYWluX3ByZWQgPC0gU2luZ2xlUih0ZXN0ID0gR2V0QXNzYXlEYXRhKGRhdGEuaW50ZWdyYXRlZCwgbGF5ZXIgPSAnY291bnRzJyksIAogICAgICAgICAgICAgICAgICAgcmVmID0gcmVmLCAKICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHJlZiRsYWJlbC5tYWluKQpkYXRhLmludGVncmF0ZWQkc2luZ2xlUi5sYWJlbHMuZmluZSA8LSBkYXRhLmludGVncmF0ZWRfZmluZV9wcmVkJGxhYmVsc1ttYXRjaChyb3duYW1lcyhkYXRhLmludGVncmF0ZWRAbWV0YS5kYXRhKSwgcm93bmFtZXMoZGF0YS5pbnRlZ3JhdGVkX2ZpbmVfcHJlZCkpXQoKZGF0YS5pbnRlZ3JhdGVkJHNpbmdsZVIubGFiZWxzLm1haW4gPC0gZGF0YS5pbnRlZ3JhdGVkX21haW5fcHJlZCRsYWJlbHNbbWF0Y2gocm93bmFtZXMoZGF0YS5pbnRlZ3JhdGVkQG1ldGEuZGF0YSksIHJvd25hbWVzKGRhdGEuaW50ZWdyYXRlZF9tYWluX3ByZWQpKV0KYGBgCgpgYGB7cn0KRGltUGxvdChkYXRhLmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzaW5nbGVSLmxhYmVscy5tYWluIikKRGltUGxvdChkYXRhLmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJzaW5nbGVSLmxhYmVscy5maW5lIikKYGBgCgpgYGB7cn0KaGVhZChzb3J0KHRhYmxlKGRhdGEuaW50ZWdyYXRlZF9maW5lX3ByZWQkbGFiZWxzKSwgZGVjcmVhc2luZz1UUlVFKSkKCmhlYWQoc29ydCh0YWJsZShkYXRhLmludGVncmF0ZWRfbWFpbl9wcmVkJGxhYmVscyksIGRlY3JlYXNpbmc9VFJVRSkpCiMgODI2IFQgY2VsbHMKYGBgCgpgYGB7cn0KIyBGaW5kaW5nIG1vcmUgd2F5cyB0byBwbG90IG91ciByZXN1bHRzLCBjaGVja2luZyBhbm5vdGF0aW9uIG9mIGNlbGxzIGFuZCBwcnVuZWQgY2VsbHMKcGxvdFNjb3JlSGVhdG1hcChkYXRhLmludGVncmF0ZWRfbWFpbl9wcmVkKQpwbG90RGVsdGFEaXN0cmlidXRpb24oZGF0YS5pbnRlZ3JhdGVkX21haW5fcHJlZCkKYGBgCiMgQ2hhbmdlIHRoZSBmaWx0ZXJpbmcgdG8gaW5jbHVkZSBhbGwgVCBDZWxscyBFWENFUFQgQ0Q0IFQgQ2VsbHMhCmBgYHtyfQpWaWV3KGRhdGFfZnJhbWUoZGF0YS5pbnRlZ3JhdGVkQG1ldGEuZGF0YVtbInNpbmdsZVIubGFiZWxzLmZpbmUiXV0pKQpgYGAKCmBgYHtyfQpWaWV3KHRhYmxlKGRhdGEuaW50ZWdyYXRlZEBtZXRhLmRhdGEkc2luZ2xlUi5sYWJlbHMuZmluZSkpCmBgYAoKCmBgYHtyfQojIEV4Y2x1ZGUgQ0Q0IFQgY2VsbHMgKHVzaW5nIG5lZ2F0aXZlIGxvb2thaGVhZCByZWdleCkKcGF0dGVybiA8LSAiVCBjZWxscyBcXCgoPyFDRDQpLipcXCkiCgojIFNob3J0ZXIgd2F5IHRvIGFkZCBtZXRhZGF0YQojIE5lZWQgdG8gYWRkIHBlcmwgPSBUUlVFIGZvciB0aGUgcmVnZXggdG8gYmUgY29tcGF0aWJsZQpkYXRhLmludGVncmF0ZWQkbm9uX2NkNCA8LSBncmVwbChwYXR0ZXJuLCBkYXRhLmludGVncmF0ZWRAbWV0YS5kYXRhJHNpbmdsZVIubGFiZWxzLmZpbmUsIHBlcmwgPSBUUlVFKQoKRGltUGxvdChkYXRhLmludGVncmF0ZWQsIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLCBncm91cC5ieSA9ICJub25fY2Q0IikKCm5vbl9jZDRfc3Vic2V0IDwtIHN1YnNldChkYXRhLmludGVncmF0ZWQsIHN1YnNldCA9IG5vbl9jZDQgPT0gVFJVRSkKYGBgCgoKCmBgYHtyfQojIFJlcnVuIFNDVHJhbnNmb3JtIG9uIHRoZSBzdWJzZXQsIHNpbmNlIHRoZSBnbG9iYWwgc3RydWN0dXJlIG9mIHZhcmlhbmNlIGNoYW5nZWQgCm5vbl9jZDRfc3Vic2V0IDwtIFNDVHJhbnNmb3JtKG5vbl9jZDRfc3Vic2V0LCB2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGQUxTRSkKCiMgU3ViLWNsdXN0ZXJpbmcgb2Ygbm9uX2NkNCBjZWxscwpub25fY2Q0X3N1YnNldCA8LSBSdW5QQ0Eobm9uX2NkNF9zdWJzZXQsIHJlZHVjdGlvbi5uYW1lID0gIm5vbl9jZDQucGNhIiwgdmVyYm9zZSA9IEZBTFNFKQpub25fY2Q0X3N1YnNldCA8LSBGaW5kTmVpZ2hib3JzKG5vbl9jZDRfc3Vic2V0LCByZWR1Y3Rpb24gPSAibm9uX2NkNC5wY2EiLCBkaW1zID0gMTozMCkKbm9uX2NkNF9zdWJzZXQgPC0gRmluZENsdXN0ZXJzKG5vbl9jZDRfc3Vic2V0LCByZXNvbHV0aW9uID0gMC41LCBjbHVzdGVyLm5hbWUgPSAibm9uX2NkNF9jbHVzdGVycyIpCm5vbl9jZDRfc3Vic2V0IDwtIFJ1blVNQVAobm9uX2NkNF9zdWJzZXQsIGRpbXMgPSAxOjMwLCByZWR1Y3Rpb24gPSAibm9uX2NkNC5wY2EiLCB2ZXJib3NlID0gRkFMU0UsIHJlZHVjdGlvbi5uYW1lID0gIm5vbl9jZDQudW1hcCIpCkRpbVBsb3Qobm9uX2NkNF9zdWJzZXQsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiLCBncm91cC5ieSA9IGMoImNvbmRpdGlvbiIsICJub25fY2Q0X2NsdXN0ZXJzIiksIGNvbWJpbmUgPSBGQUxTRSkKYGBgCgoKYGBge3J9CiMgRmluZGluZyBERSBnZW5lcwpJZGVudHMobm9uX2NkNF9zdWJzZXQpIDwtICJub25fY2Q0X2NsdXN0ZXJzIgpub25fY2Q0X3N1YnNldCA8LSBQcmVwU0NURmluZE1hcmtlcnMobm9uX2NkNF9zdWJzZXQpCnRjZWxsLm5vbl9jZDQubWFya2VycyA8LSBGaW5kTWFya2Vycyhub25fY2Q0X3N1YnNldCwgaWRlbnQuMSA9IDAsIGlkZW50LjIgPSAyKQoKdGNlbGwubm9uX2NkNC5tYXJrZXJzCmBgYAoKYGBge3J9CkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJHY250MSIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiR3ptYiIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiU3BuIiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJTZWxsIiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJQcmYxIiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCmBgYApgYGB7cn0KRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIlNwbiIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiQ3hjcjMiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIkhhdmNyMiIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiSWZuZyIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiSWNvcyIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpgYGAKCgpgYGB7cn0KRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIlByZG0xIiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJUb3giLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIkd6bWsiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKI0ZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJHYm1hIiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpIE5PVCBGT1VORAojRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIkd6bWgiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikgTk9UIEZPVU5ECgpgYGAKCgpgYGB7cn0KRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIkd6bWIiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIkxhZzMiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIlRpZ2l0IiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJJcmY0IiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCkZlYXR1cmVQbG90KG5vbl9jZDRfc3Vic2V0LCBmZWF0dXJlcyA9ICJUY2Y3IiwgcmVkdWN0aW9uID0gIm5vbl9jZDQudW1hcCIpCmBgYAoKCmBgYHtyfQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiUGRjZDEiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKRmVhdHVyZVBsb3Qobm9uX2NkNF9zdWJzZXQsIGZlYXR1cmVzID0gIlRuZiIsIHJlZHVjdGlvbiA9ICJub25fY2Q0LnVtYXAiKQpGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSAiVGJ4MjEiLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKYGBgCgoKI1NhdmUgdGhlIHBsb3RzIGFzIFBOR3MKCmxpYnJhcnkoZ2dwbG90MikKCiMgTGlzdCBnZW5lcyAocmVtb3ZlIGdlbmVzIHRoYXQgd2VyZSBub3QgZm91bmQpCmdlbmVzIDwtIGMoIkdjbnQxIiwgIkd6bWIiLCAiU3BuIiwgIlNlbGwiLCAiUHJmMSIsICJDeGNyMyIsICJIYXZjcjIiLCAiSWZuZyIsICJJY29zIiwKICAgICAgICAgICAiUHJkbTEiLCAiVG94IiwgIkd6bWsiLCAiTGFnMyIsICJUaWdpdCIsICJJcmY0IiwgIlRjZjciLCAKICAgICAgICAgICAiUGRjZDEiLCAiVG5mIiwgIlRieDIxIikKCiMgTG9vcCB0aHJvdWdoIHRoZSBnZW5lcyBhbmQgY3JlYXRlL3NhdmUgcGxvdHMKZm9yIChnZW5lIGluIGdlbmVzKSB7CiAgcGxvdCA8LSBGZWF0dXJlUGxvdChub25fY2Q0X3N1YnNldCwgZmVhdHVyZXMgPSBnZW5lLCByZWR1Y3Rpb24gPSAibm9uX2NkNC51bWFwIikKICBnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZTAoIm5vbl9jZDRfIiwgZ2VuZSwgIi5wbmciKSwgcGxvdCA9IHBsb3QsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCwgZHBpID0gMzAwKQoKCgoKYGBge3J9CiMgRnJvbSB0aGUgbGlzdCBEci4gS3J1bW1leSBzZW50LCBmaW5kIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBvZiB0aGUgZ2VuZXMgb2YgaW50ZXJlc3QKYGBgCgoKYGBge3J9CiMgTG9vayBiYWNrIHRvIGp1c3QgTk9OLUNENCBUIGNlbGxzIHRvIHNlZSBpZiB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgKGNvbXBsZXRlKQpgYGAKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK